#ifndef _WSC_SUPPLICANT_H
#define _WSC_SUPPLICATN_H

#include "common.h"

#ifndef ETH_ALEN
#define ETH_ALEN 6
#endif

//#define IFNAMSIZ                           16
#define IEEE80211_MAX_SSID                 34
#define SSID_MAX_WPA_IE_LEN                40

#define IEEE80211_CAP_ESS                  0x0001
#define IEEE80211_CAP_IBSS                 0x0002
#define IEEE80211_CAP_PRIVACY              0x0010

typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP } wpa_alg;
typedef enum { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP,
	       CIPHER_WEP104 } wpa_cipher;
typedef enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE,
	       KEY_MGMT_802_1X_NO_WPA, KEY_MGMT_WPA_NONE } wpa_key_mgmt;

typedef enum { SM_INIT, SM_START, SM_SEND_IDENTITY, SM_START_WPS_NEGOCIATION, SM_SCAN, SM_CONNECT } wps_state;

#define WFA_IDENTITY     "WFA-SimpleConfig-Enrollee-1-0"

#define GENERIC_INFO_ELEM 0xdd
#define RSN_INFO_ELEM 0x30
#define MAX_SOCK_NUM  5

struct eloop_timeout {
	struct timeval time;
	void *eloop_data;
	void *user_data;
	struct eloop_timeout *next;
};

struct wsc_drv
{
    char *wds_ap_ifname;
    char *ifname;
    char *bridge_ifname;
    char wds_ap_ifnameBody[10];
    char ifnameBody[10];
    char bridge_ifnameBody[10];
    int ioctl_sock;
    int event_sock;
    int ifindex;
    struct l2_packet_data *l2;
    struct l2_packet_data *l2_br;
    int sock[MAX_SOCK_NUM];
    int sock_num;
    int max_sock_num;
    char *ssid;
    char ssidBody[32];
    int ssid_len;
    char *PBCssid;
    char PBCssidBody[32];
    int PBCssid_len;

    char connect2BSSID[6];
    char pushButtonPress;
    char *pin;
    char pinBody[10];
    int debug;
    int method;
    int alive;
    int nodaemon;
    int sup_delay;
    int policy;
    int serviceType;
    pid_t wpa_supplicant_pid;
    pid_t hostapd_pid;
    pid_t wsccmd_pid;
    struct eloop_timeout *timeout;
    struct l2_packet_data *l2_sock[MAX_SOCK_NUM];
    wps_state state;
    //char ssid[IEEE80211_MAX_SSID];
    u8 bssid[ETH_ALEN];
    u8 blockAPNum;
    u8 blockBssid[32][ETH_ALEN];
    int blockTime[32];
    char rspbuf[2048];
    int resendTime;
    int pbcAPNum;
    u8 startOP;

	/* Wireless Extension version info */
    u8 we_version_compiled; /* Must be WIRELESS_EXT */
    u8 we_version_source;   /* Last update of source */
    u16 connect_try;
    u8 wpsBSSID[64][6];
    u16 wpsAPNum;
    u8 pbcActivates;
    u8 CONFIG_MANUFACTURER[128];
    u8 CONFIG_MODEL_NAME[128];
    u8 CONFIG_MODEL_NUMBER[128];
    u8 CONFIG_DEVICE_NAME[128];
    u8 CONFIG_DEVICE_UUID[16];
    u8 CONFIG_PRIMARY_DEVICE_TYPE[8];
    u8 CONFIG_RFBANDS;



} __attribute__ ((packed));

struct ieee802_1x_hdr {
	u8 version;
	u8 type;
	u16 length;
	/* followed by length octets of data */
} __attribute__ ((packed));

enum { IEEE802_1X_TYPE_EAP_PACKET = 0,
       IEEE802_1X_TYPE_EAPOL_START = 1,
       IEEE802_1X_TYPE_EAPOL_LOGOFF = 2,
       IEEE802_1X_TYPE_EAPOL_KEY = 3,
       IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT = 4
};

enum { wlanProfileSecurityMode_eOpen    = 1,
       wlanProfileSecurityMode_eWep     = 2,
       wlanProfileSecurityMode_eWpaPsk  = 4,
       wlanProfileSecurityMode_eWpa2Psk = 8,
};

/**
 * struct wpa_driver_associate_params - Association parameters
 * Data for struct wpa_driver_ops::associate().
 */
struct wpa_driver_associate_params {
	/**
	 * bssid - BSSID of the selected AP
	 * This can be %NULL, if ap_scan=2 mode is used and the driver is
	 * responsible for selecting with which BSS to associate. */
	const u8 *bssid;

	/**
	 * ssid - The selected SSID
	 */
	const u8 *ssid;
	size_t ssid_len;

	/**
	 * freq - Frequency of the channel the selected AP is using
	 * Frequency that the selected AP is using (in MHz as
	 * reported in the scan results)
	 */
	int freq;

	/**
	 * wpa_ie - WPA information element for (Re)Association Request
	 * WPA information element to be included in (Re)Association
	 * Request (including information element id and length). Use
	 * of this WPA IE is optional. If the driver generates the WPA
	 * IE, it can use pairwise_suite, group_suite, and
	 * key_mgmt_suite to select proper algorithms. In this case,
	 * the driver has to notify wpa_supplicant about the used WPA
	 * IE by generating an event that the interface code will
	 * convert into EVENT_ASSOCINFO data (see wpa_supplicant.h).
	 * When using WPA2/IEEE 802.11i, wpa_ie is used for RSN IE
	 * instead. The driver can determine which version is used by
	 * looking at the first byte of the IE (0xdd for WPA, 0x30 for
	 * WPA2/RSN).
	 */
	const u8 *wpa_ie;
	/**
	 * wpa_ie_len - length of the wpa_ie
	 */
	size_t wpa_ie_len;

	/* The selected pairwise/group cipher and key management
	 * suites. These are usually ignored if @wpa_ie is used. */
	wpa_cipher pairwise_suite;
	wpa_cipher group_suite;
	wpa_key_mgmt key_mgmt_suite;

	/**
	 * auth_alg - Allowed authentication algorithms
	 * Bit field of AUTH_ALG_*
	 */
	int auth_alg;

	/**
	 * mode - Operation mode (infra/ibss) IEEE80211_MODE_*
	 */
	int mode;
    int privacy;

};

struct wpa_scan_result {
        u8 bssid[ETH_ALEN];
        u8 ssid[32];
        size_t ssid_len;
        u8 wpa_ie[SSID_MAX_WPA_IE_LEN];
        size_t wpa_ie_len;
        u8 rsn_ie[SSID_MAX_WPA_IE_LEN];
        size_t rsn_ie_len;
        int freq;
        u16 caps;
        int qual;
        int noise;
        int level;
        int maxrate;
};

#define    WSC_ERROR_INIT_SOCKET        0x00000001
#define    DEFAULT_EAPOL_VERSION                 1

#define    WSC_TIMEOUT_INIT                      2
#define    WSC_TIMEOUT_DEFAULT                  10
#define    WSC_TIMEOUT_NULL                      0
#define    WSC_TIMEOUT_SCAN                      3
#define    WSC_TIMEOUT_NO_RESPONSE               5
#define    WSC_TIMEOUT_HANDSHAKING             120

#define    WSC_DBG_INIT                 0x00000001
#define    WSC_DBG_CONNECT              0x00000002
#define    WSC_DBG_MSGWSC               0x00000004
#define    WSC_DBG_HANDSHAKING          0x00000008
#define    WSC_DBG_PROFILE              0x00000010

/* Functions declaration */
int wsc_supplicant_init(struct wsc_drv *wsc_drv);
void wsc_supplicant_destroy(struct wsc_drv *wsc_drv);
int wsc_send_udp_data(struct wsc_drv *wsc_drv, char *buf, int len);
int wsc_write_wpa_supplicant_conf(FILE *fp, int wHead, char *ssid, int key_mgmt, int enc,
        int keyIndex, char *nwKey, u32 nwkeylen);
int wsc_write_wsccmd_conf(char *ssid, int key_mgmt, int enc,
        int keyIndex, char *nwKey, u32 nwkeylen);
int wsc_write_hostapd_conf(char *ssid, int key_mgmt,
        char *nwKey, u32 nwkeylen);

int wsc_invoke_wpa_supplicant(char *ifname, char *path, char *config);
int wsc_invoke_wsccmd(char *path, int radio_num);
int wsc_invoke_hostapd(char *path, char *config);

void wsc_printf(int level, char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));

#endif

